home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 August: Tool Chest / Dev.CD Aug 98 TC.toast / Sample Code / Interapplication Communication / MenuScripter 4.0 / Sources / MSAECompare.c < prev    next >
Encoding:
Text File  |  1996-07-09  |  7.5 KB  |  316 lines  |  [TEXT/CWIE]

  1. // MSAECompare.c
  2. //
  3. // Original version by Jon Lansdell and Nigel Humphreys.
  4. // 4.0 and 3.1 updates by Greg Sutton.
  5. // ©Apple Computer Inc 1996, all rights reserved.
  6.  
  7. /*
  8.     Changes for 4.0
  9.     
  10.     29-Feb-96 : GS : Added ability to compare menu and menu item properties.
  11.     22-Apr-96 : GS : Comparing text begins, ends, and contains is now true if equal.
  12. */
  13.  
  14. #include "MSAECompare.h"
  15.  
  16. #include <AEPackObject.h>
  17. #include "MSGlobals.h"
  18. #include "MSUtils.h"
  19. #include "MSAEUtils.h"
  20. #include "MSWindow.h"
  21. #include "MSFile.h"
  22. #include "MSAppleEvents.h"
  23.  
  24. #include "MSToken.h"
  25. #include "MSAECountElements.h"
  26. #include "MSAEGetData.h"
  27.  
  28. #include <string.h>
  29.  
  30.  
  31. #pragma segment AppleEvent
  32.  
  33.  
  34. OSErr    InstallObjectCallbacks(void)
  35. {
  36.     OSErr    err;
  37.  
  38.     err = AESetObjectCallbacks(NewOSLCompareProc(MyCompareProc),
  39.                                 NewOSLCountProc(MyCountProc),
  40.                                 NULL, NULL, NULL, NULL, NULL);
  41.                                 
  42.     return(err);
  43. }
  44.  
  45.  
  46. pascal OSErr    MyCompareProc(DescType oper, const AEDesc* obj1, const AEDesc* obj2, Boolean* result)
  47. {
  48.     AEDesc        desc1     = {typeNull, NULL};
  49.     AEDesc        desc2     = {typeNull, NULL};
  50.     AEDesc        tempDesc = {typeNull, NULL};
  51.     OSErr        err;
  52.     
  53.     err = ExtractData(obj1, &desc1);
  54.     if (err != noErr) goto done;
  55.     err = ExtractData(obj2, &desc2);
  56.     if (err != noErr) goto done;
  57.  
  58.     // Make sure the 2 data types are the same
  59.     if (desc1.descriptorType != desc2.descriptorType)
  60.     {
  61.         err = AEDuplicateDesc(&desc2, &tempDesc);
  62.         if (err != noErr) goto done;
  63.         err = AEDisposeDesc(&desc2);
  64.         err = AECoerceDesc(&tempDesc, desc1.descriptorType, &desc2);
  65.         if (err != noErr)                        // If we can't coerce one way, try
  66.         {                                        // the opposite way.
  67.             err = AEDuplicateDesc(&tempDesc, &desc2);    // We disposed of desc2
  68.             err = AEDisposeDesc(&tempDesc);
  69.             err = AEDuplicateDesc(&desc1, &tempDesc);
  70.             if (err != noErr) goto done;
  71.             err = AEDisposeDesc(&desc1);
  72.             err = AECoerceDesc(&tempDesc, desc2.descriptorType, &desc1);
  73.             if (err != noErr) goto done;
  74.         }
  75.     }
  76.     
  77.     // Now that we know that the 2 types are the same, go ahead and run the compare
  78.     switch(desc1.descriptorType)
  79.     {
  80.         case typeChar:
  81.             err = MyCompareText(oper, &desc1, &desc2, result);
  82.             break;
  83.         
  84.         case typeShortInteger:
  85.         case typeLongInteger:
  86.             err = MyCompareInteger(oper, &desc1, &desc2, result);
  87.             break;
  88.  
  89.         case typeBoolean:
  90.             err = MyCompareBoolean(oper, &desc1, &desc2, result);
  91.             break;
  92.                 
  93.         default:
  94.             err = errAEWrongDataType;
  95.     }
  96.     
  97. done:
  98.     if (desc1.dataHandle)
  99.         (void) AEDisposeDesc(&desc1);
  100.     if (desc2.dataHandle)
  101.         (void) AEDisposeDesc(&desc2);
  102.     if (tempDesc.dataHandle)
  103.         (void) AEDisposeDesc(&tempDesc);
  104.     
  105.     return(err);
  106. }
  107.  
  108.  
  109. OSErr    ExtractData(const AEDesc *sourceDesc, AEDesc *theData)
  110. {
  111.     AEDesc        intermediateDesc = {typeNull, NULL};
  112.     OSErr        err;
  113.     
  114.     // This routine can receive: An Object specifier, an object token, a property token, or
  115.     // some data (TEXT, Rectangle, etc.). It needs to convert whatever it's handed into data
  116.     // and return that.
  117.     
  118.     // If we don't have any data, complain
  119.     if (sourceDesc->descriptorType == typeNull || sourceDesc->dataHandle == NULL)
  120.         return(errAENoSuchObject);
  121.     
  122.     // If it's an object specifier, resolve into a token
  123.     if (sourceDesc->descriptorType == typeObjectSpecifier)
  124.         err = AEResolve(sourceDesc, kAEIDoMinimum, &intermediateDesc);
  125.     else    // Otherwise, just copy it
  126.         err = AEDuplicateDesc(sourceDesc, &intermediateDesc);
  127.  
  128.     if (err != noErr) goto done;
  129.     
  130.     // Now that we have a token, read from it
  131.     switch (intermediateDesc.descriptorType)
  132.     {
  133.         case typeMyApplProp:
  134.         case typeMyTextProp:
  135.         case typeMyWindowProp:
  136.         case typeMyMenuProp:
  137.         case typeMyMenuItemProp:
  138.         case typeMyText:
  139.             err = HandleGetData(&intermediateDesc, typeWildCard, theData);
  140.             break;
  141.  
  142.         default:
  143.             // This is probably raw data , so pass it back up the line
  144.             err = AEDuplicateDesc(&intermediateDesc, theData);
  145.     }
  146.  
  147. done:
  148.     if (intermediateDesc.dataHandle)
  149.         (void) AEDisposeDesc(&intermediateDesc);
  150.  
  151.     return(err);
  152. }
  153.  
  154.  
  155. OSErr    MyCompareText(DescType oper, const AEDesc *desc1, const AEDesc *desc2, Boolean *result)
  156. {
  157.     int        compareResult;
  158.     long    compareSize;
  159.     long    textSize1, textSize2;
  160.     char    *testStr, *compareStr;
  161.     OSErr    err = noErr;
  162.     
  163.     textSize1 = GetHandleSize(desc1->dataHandle);
  164.     HLockHi(desc1->dataHandle);
  165.     textSize2 = GetHandleSize(desc2->dataHandle);
  166.     HLockHi(desc2->dataHandle);
  167.     if (textSize1 < textSize2)
  168.     {
  169.         switch (oper)
  170.         {
  171.             case kAEBeginsWith:        // Can't begin or end or contain any string
  172.             case kAEEndsWith:        // longer than itself
  173.             case kAEContains:
  174.                 *result = false;
  175.                 return(noErr);
  176.         }
  177.     
  178.         compareSize = textSize1;
  179.     }
  180.     else
  181.         compareSize = textSize2;
  182.     
  183.     switch (oper)
  184.     {
  185.         case kAEEndsWith:            // Offset to end of string
  186.             testStr = (char *)(*desc1->dataHandle + textSize1 - textSize2);    
  187.             break;
  188.         
  189.         case kAEContains:
  190.             testStr = NewPtr(textSize1 + 1);
  191.             BlockMove(*desc1->dataHandle, testStr, textSize1);
  192.             testStr[textSize1] = '\0';
  193.             compareStr = NewPtr(textSize2 + 1);
  194.             BlockMove(*desc2->dataHandle, compareStr, textSize2);
  195.             compareStr[textSize2] = '\0';
  196.             *result = (NULL != strstr(testStr,compareStr));
  197.             DisposePtr(testStr);
  198.             DisposePtr(compareStr);
  199.             return(noErr);
  200.         
  201.         default:
  202.             testStr = (char *)*desc1->dataHandle;
  203.     }
  204.     
  205.     compareResult = strncmp(testStr, (char *)*desc2->dataHandle, compareSize);
  206.     
  207.     HUnlock(desc1->dataHandle);
  208.     HUnlock(desc2->dataHandle);
  209.  
  210.     switch (oper)
  211.     {
  212.         case kAEEquals:
  213.             *result = (textSize1 == textSize2 && compareResult == 0);
  214.             break;
  215.  
  216.         case kAEBeginsWith:
  217.         case kAEEndsWith:
  218.             *result = (compareResult == 0);
  219.             break;
  220.  
  221.         case kAELessThan:
  222.             *result = (compareResult < 0);
  223.             break;
  224.         
  225.         case kAELessThanEquals:
  226.             *result = (compareResult <= 0);
  227.             break;
  228.         
  229.         case kAEGreaterThan:
  230.             *result = (compareResult > 0);
  231.             break;
  232.         
  233.         case kAEGreaterThanEquals:
  234.             *result = (compareResult >= 0);
  235.             break;
  236.         
  237.         default:
  238.             err = errAEBadTestKey;
  239.     }
  240.  
  241.     return(err);
  242. }
  243.  
  244.  
  245. OSErr    MyCompareInteger(DescType oper, const AEDesc *desc1, const AEDesc *desc2, Boolean *result)
  246. {
  247.     long    num1, num2;
  248.     AEDesc    longDesc = {typeNull, NULL};
  249.     OSErr    err;
  250.     
  251.     // Make each number is a long integer (in case it's a short integer) before extracting the data
  252.     err = AECoerceDesc(desc1, typeLongInteger, &longDesc);
  253.     if (err != noErr) goto done;
  254.     num1 = **(long **)longDesc.dataHandle;
  255.     (void) AEDisposeDesc(&longDesc);    // We're done with longDesc, so dispose of it
  256.     longDesc.dataHandle = NULL;            // Mark this as disposed
  257.     
  258.     err = AECoerceDesc(desc2, typeLongInteger, &longDesc);
  259.     if (err != noErr) goto done;
  260.     num2 = **(long **)longDesc.dataHandle;
  261.     // No need to dispose of this descriptor, as the code at "done" will do it for us
  262.     
  263.     switch (oper)
  264.     {
  265.         case kAEEquals:
  266.             *result = (num1 == num2);
  267.             break;
  268.         
  269.         case kAELessThan:
  270.             *result = (num1 < num2);
  271.             break;
  272.         
  273.         case kAELessThanEquals:
  274.             *result = (num1 <= num2);
  275.             break;
  276.         
  277.         case kAEGreaterThan:
  278.             *result = (num1 > num2);
  279.             break;
  280.         
  281.         case kAEGreaterThanEquals:
  282.             *result = (num1 >= num2);
  283.             break;
  284.         
  285.         default:
  286.             err = errAEBadTestKey;
  287.     }
  288.     
  289. done:
  290.     if (longDesc.dataHandle)
  291.         (void) AEDisposeDesc(&longDesc);
  292.  
  293.     return err;
  294. } // MyCompareInteger
  295.  
  296.  
  297. OSErr    MyCompareBoolean (DescType oper, const AEDesc *desc1, const AEDesc *desc2, Boolean *result)
  298. {
  299.     Boolean    bool1, bool2;
  300.     OSErr    err = noErr;
  301.     
  302.     // Apple events defines a boolean as a 1-byte value containing 1 for TRUE and 0 for FALSE
  303.     // We'll use a test to convert this into C's boolean notation, just to make this easier to
  304.     // debug
  305.     
  306.     bool1 = (**(char **)desc1->dataHandle) != 0;
  307.     bool2 = (**(char **)desc2->dataHandle) != 0;
  308.     
  309.     if (oper == kAEEquals) 
  310.         *result = (bool1 == bool2);
  311.     else
  312.         err = errAEBadTestKey;        // No other tests make sense
  313.  
  314.     return err;
  315. } // MyCompareBoolean
  316.